package com.vidmt.api.modules.sys.api;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.vidmt.api.common.anno.ApiDoc;
import com.vidmt.api.common.exceptions.BadParamException;
import com.vidmt.api.common.pojo.ApiResultServer;
import com.vidmt.api.common.utils.CommUtil;
import com.vidmt.api.common.utils.StrUtil;
import com.vidmt.api.common.web.ApiController;
import com.vidmt.api.modules.sys.Enums.FileType;
import com.vidmt.api.modules.sys.Enums.LogType;
import com.vidmt.api.modules.sys.entity.Log;
import com.vidmt.api.modules.sys.entity.User;
import com.vidmt.api.modules.sys.providers.ResProvider;
import com.vidmt.api.modules.sys.service.LogService;
import com.vidmt.api.modules.sys.service.UserService;
import com.vidmt.api.modules.sys.shiro.ShiroUtil;
import com.vidmt.api.modules.sys.utils.ResUtil;

@Controller
@ResponseBody
@RequestMapping("/vplugin")
public class ApiFileController extends ApiController {
	private static final Logger log = LoggerFactory.getLogger(ApiFileController.class);
	@Autowired
	private UserService userService;
	@Autowired
	private ResProvider resProvider;
	@Autowired
	private LogService logService;

	@ApiDoc({ "用户的头像等个人文件用于临时调试", "" })
	@RequestMapping(value = "/" + ResUtil.USER_FILES_DIR + "/**", method = RequestMethod.GET)
	public ResponseEntity<byte[]> download(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String relPath = req.getServletPath();
		try {
			byte[] datas = resProvider.downloadFile(relPath);
			File tmpFile = new File(relPath);
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			headers.setContentDispositionFormData("attachment", tmpFile.getName());
			return new ResponseEntity<byte[]>(datas, headers, HttpStatus.CREATED);
		} catch (FileNotFoundException e) {
			req.setAttribute("exception", new FileNotFoundException("请求的文件不存在"));
			resp.sendError(HttpServletResponse.SC_NOT_FOUND, relPath + " not exist");
			return null;
		}

	}

	@ApiDoc({ "type", "AVATAR/PHOTO/LOG,如果是LOG，则要求客户端上传文件后自行删除本地文件，服务端不进行重复检查" })
	@ApiDoc({ "files", "客户端传过来的值必须用files作为名字，如果有多个，就用多个files" })
	@ApiDoc({ "os", "可以为空，如果type=LOG,则请填写此参数" })
	@ApiDoc({ "客户端自行检查文件是否为空", "" })
	@RequestMapping(value = "/api/1/file/upload.*", method = RequestMethod.POST)
	public ApiResultServer upload(FileType type, @RequestParam("files") List<MultipartFile> files, String os)
			throws IOException, BadParamException {
		if (CommUtil.isEmpty(files)) {
			throw new BadParamException("没有上传任何文件");
		}
		User user = ShiroUtil.getCurrentUser();
		Long uid = user.getId();

		if (type == FileType.AVATAR) {
			String avatarDir = ResUtil.buildResDir(type, uid);
			String relpath = ResUtil.buildFileSavePath(type, uid, files.get(0).getOriginalFilename());
			InputStream is = files.get(0).getInputStream();
			try {
				resProvider.deleteFile(avatarDir);
				resProvider.uploadFile(relpath, is);
			} finally {
				CommUtil.close(is);
			}
			user.setAvatarUri(relpath);
			userService.update(user);
			return new ApiResultServer(relpath);
		} else if (type == FileType.PHOTO) {
			StringBuilder resUri = new StringBuilder(user.getPhotoUri());
			if (resUri.length() > 0) {
				resUri.append("|");
			}
			for (MultipartFile file : files) {
				String relpath = ResUtil.buildFileSavePath(type, uid, file.getOriginalFilename());
				InputStream is = file.getInputStream();
				try {
					resProvider.uploadFile(relpath, is);
					resUri.append(relpath + "|");
				} finally {
					CommUtil.close(is);
				}

			}
			if (resUri.length() > 0) {
				resUri.deleteCharAt(resUri.length() - 1);
			}
			user.setPhotoUri(resUri.toString());
			userService.update(user);
			return new ApiResultServer(resUri.toString());
		} else if (type == FileType.LOG) {
			for (MultipartFile file : files) {
				String content = StrUtil.newutf8(file.getBytes());
				Log log = new Log();
				log.setType(LogType.CLIENT);
				log.setOperator(uid);
				log.setTime(new Date());
				log.setContent(os + ":" + file.getOriginalFilename() + ":" + content);
				logService.save(log);
			}
		}
		throw new BadParamException();
	}

	@ApiDoc({ "type", "AVATAR/PHOTO" })
	@ApiDoc({ "fileNames", "文件的名字，不带文件夹名字" })
	@RequestMapping(value = "/api/1/file/delete.*", method = RequestMethod.POST)
	public ApiResultServer delete(FileType type, String[] fileNames) throws IOException, BadParamException {
		User user = ShiroUtil.getCurrentUser();
		Long uid = user.getId();

		if (type == FileType.AVATAR) {
			String filePath = ResUtil.buildFileSavePath(type, uid, fileNames[0]);
			resProvider.deleteFile(filePath);
			user.setAvatarUri(null);
			userService.update(user);
			return new ApiResultServer();
		} else if (type == FileType.PHOTO) {
			String origPhotoUri = user.getPhotoUri();
			String[] origPhotoArr = origPhotoUri.split("\\|");
			for (String fileName : fileNames) {
				String relpath = ResUtil.buildFileSavePath(type, uid, fileName);
				resProvider.deleteFile(relpath);
				for (int i = 0; i < origPhotoArr.length; i++) {
					if (origPhotoArr[i].endsWith(fileName)) {
						origPhotoArr[i] = null;
						break;
					}
				}
			}
			String newUri = StrUtil.join("|", origPhotoArr);
			user.setPhotoUri(newUri);
			userService.update(user);
			return new ApiResultServer(newUri);
		}
		throw new BadParamException();
	}
}
